#include "bsp_spi.h"
#include "at32f403a_407.h"
#include <string.h>
#include "cbb_init.h"

void spi3_init(void){

    // 时钟
    crm_periph_clock_enable(CRM_SPI3_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

    gpio_init_type gpio_init_struct;
    spi_init_type spi_init_struct;

    /* configure the cs pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_15;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);
    gpio_bits_write(GPIOA, GPIO_PINS_15, 1);

    /* configure the SCK pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_3;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOB, &gpio_init_struct);

    /* configure the MISO pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_4;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOB, &gpio_init_struct);

    /* configure the MOSI pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_5;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOB, &gpio_init_struct);

    /* configure param */
    spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
    spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
    spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
    spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
    spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_32;
    spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;
    spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
    spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
    spi_init(SPI3, &spi_init_struct);

    // 使能SPI
    spi_enable(SPI3, TRUE);

}
INIT_PORT_BSP(spi3_init);

#if 0
uint8_t spi1_dma_transmit_receive(uint8_t* pu8TxBuffer, uint8_t* pu8RxBuffer, uint32_t u32Len){
    /* DMA失能 */
    DMA_Cmd(DMA1_Channel2, DISABLE); // 使能DMA通道2
    DMA_Cmd(DMA1_Channel3, DISABLE); // 使能DMA通道3
    SPI_I2S_DMACmd(SPI1,  SPI_I2S_DMAReq_Rx | SPI_I2S_DMAReq_Tx, DISABLE);

    /* 配置DMA通道 */
    if (pu8TxBuffer != NULL) {
        /* 配置发送DMA通道 */
        DMA1_Channel3->CMAR = (uint32_t)pu8TxBuffer;
        DMA1_Channel3->CNDTR = u32Len;
        DMA_Cmd(DMA1_Channel3, ENABLE);
    }

    if (pu8RxBuffer != NULL) {
        /* 配置接收DMA通道 */
        DMA1_Channel2->CMAR = (uint32_t)pu8RxBuffer;
        DMA1_Channel2->CNDTR = u32Len;
        DMA_Cmd(DMA1_Channel2, ENABLE);
    }

    /* 使能SPI DMA请求 */
    if (pu8TxBuffer != NULL && pu8RxBuffer != NULL) {
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx | SPI_I2S_DMAReq_Tx, ENABLE);
    } else if (pu8TxBuffer != NULL) {
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
    } else if (pu8RxBuffer != NULL) {
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
    }

    /* 等待DMA传输完成 */
    if (pu8TxBuffer != NULL) {
        while (DMA_GetFlagStatus(DMA1_FLAG_TC3) == RESET);
        DMA_ClearFlag(DMA1_FLAG_TC3);
    }

    if (pu8RxBuffer != NULL) {
        while (DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET);
        DMA_ClearFlag(DMA1_FLAG_TC2);
    }

    /* 等待SPI空闲 */
    while ((SPI1->SR & SPI_SR_BSY) != 0);

    return 0;
}
#endif

void spi3_cs(uint8_t u8State){
    gpio_bits_write(GPIOA, GPIO_PINS_15,u8State);
}

// static
uint8_t spi3_swap(uint8_t data){

    uint16_t retry = 0;

    // 等待SPI空闲
    while(SPI3->sts_bit.bf != 0){
        retry++;
        if(retry > 1000)return 1;
    }

    // 等待发送区为空
    while(SPI3->sts_bit.tdbe == 0){
        retry++;
        if(retry > 1000)return 1;
    }

    // 发送数据
    SPI3->dt = data;

    // 等待接收完数据
    while(SPI3->sts_bit.rdbf == 0){
        retry++;
        if(retry > 1000) return 1;
    }

    // 读取数据
    return SPI3->dt;
}

uint8_t spi3_transmit_receive(uint8_t* pu8TxBuffer, uint8_t* pu8RxBuffer, uint32_t u32Len){

    // 收发
    if(pu8TxBuffer != NULL && pu8RxBuffer != NULL){
        for(uint32_t i=0;i<u32Len;i++){
            pu8RxBuffer[i] = spi3_swap(pu8TxBuffer[i]);
        }
    }

    // 发送
    if(pu8TxBuffer != NULL && pu8RxBuffer == NULL){
        for(uint32_t i=0;i<u32Len;i++){
            spi3_swap(pu8TxBuffer[i]);
        }
    }

    // 接收
    if(pu8TxBuffer == NULL && pu8RxBuffer != NULL){
        for(uint32_t i=0;i<u32Len;i++){
            pu8RxBuffer[i] = spi3_swap(0xFF);
        }
    }

    return 0;

}




